﻿using System;
using System . Collections . Generic;
using System . Collections . ObjectModel;
using System . Linq;
using System . Collections;
using System . Xml . Linq;
using System . Text;
using System . Threading . Tasks;

namespace GameClassLibrary
{
    public class Game
    {
        #region Starting

        public DateTime StartDate { get; private set; }

        public long StartMoney { get; private set; }

        public TimeSpan GameTime { get; private set; }

        public long ConditionsToWin { get; private set; }

        #endregion

        public Players . Player CurrentPlayer { get; private set; }

        public void NextPlayer ( )
        {
            if ( Players . IndexOf ( CurrentPlayer ) + 1 < Players . Count )
            {
                CurrentPlayer = Players [ Players . IndexOf ( CurrentPlayer ) + 1 ];
            }
            else
            {
                NextDay ( );
                CurrentPlayer = Players . First ( );
            }
        }

        public bool IsStarted { get; set; } = false;

        public static Game Current { get; private set; }

        public Random Randomer { get; private set; }

        public DateTime EndDate { get { return StartDate + GameTime; } }

        public TimeSpan RemainingTime { get { return EndDate - Date; } }

        public Calendars . Calendar Calendar { get; private set; }

        public DateTime Date { get; set; }

        public DateTime NextDate
        {
            get
            {
                return Date . AddDays ( 1 );
            }
        }

        public Maps . Map Map { get; private set; }

        public GovermentControl GovermentControl { get; set; }

        public List<Buffs . Buff> Buffs { get; private set; }

        public List<Players . Player> Players { get; private set; }

        public Stocks . StockMarket StockMarket { get; set; }

        public void NextDay ( )
        {
            if ( true )
            {

            }
        }

        public void Start ( StartGameParameters parameters )
        {


            listForLoad = new List<Tuple<GameObject , Type , string , long>> ( );

            StartMoney = parameters . StartMoney;

            GameTime = parameters . GameTime;

            Map = new Maps . Map ( );

            StockMarket = new Stocks . StockMarket ( );

            ConditionsToWin = parameters . ConditionsToWin;



            foreach ( var item in listForLoad )
            {
                item . Item2 . GetProperty ( item . Item3 ) . SetValue ( item . Item1 , GameObject . GetObject ( item . Item4 ) , null );
            }

            listForLoad = null;

        }

        public void Start ( XDocument document )
        {
            listForLoad = new List<Tuple<GameObject , Type , string , long>> ( );




            foreach ( var item in listForLoad )
            {
                if ( Attribute . GetCustomAttribute ( item . Item2 . GetProperty ( item . Item3 ) , typeof ( SaveReferenceAttribute ) ) != null )
                {
                    item . Item2 . GetProperty ( item . Item3 ) . SetValue ( item . Item1 , GameObject . GetObject ( item . Item4 ) , null );
                }
                else
                {
                    if ( Attribute . GetCustomAttribute ( item . Item2 . GetProperty ( item . Item3 ) , typeof ( SaveReferenceListAttribute ) ) != null )
                    {
                        ( item . Item2 . GetProperty ( item . Item3 ) . GetValue ( item . Item1 , null ) as List<GameObject> ) . Add ( GameObject . GetObject ( item . Item4 ) );
                    }
                }
            }




            listForLoad = null;

        }

        public XDocument Save ( )
        {
            XDocument temp=new XDocument();

            XElement game=new XElement("Game");

            game . SetAttributeValue ( "StartDate" , StartDate );
            game . SetAttributeValue ( "StartMoney" , StartMoney );
            game . SetAttributeValue ( "GameTime" , GameTime );
            game . SetAttributeValue ( "ConditionsToWin" , ConditionsToWin );
            game . SetAttributeValue ( "IsStarted" , IsStarted );
            game . SetAttributeValue ( "Date" , Date );

            XElement player=new XElement("Player");

            foreach ( var item in Players )
            {
                player . Add ( item . Save ( ) );
            }

            game . Add ( player );

            XElement map=Map.Save();

            game . Add ( map );

            XElement calendar=Calendar.Save();

            game . Add ( calendar );

            temp . Add ( game );

            return temp;
        }



        public Game ( )
        {
            Current = this;
        }

        public static void RegisterForLoad ( GameObject obj , Type type , string propertieName , long index )
        {
            if ( listForLoad == null )
            {
                throw new Exception ( );
            }

            listForLoad . Add ( new Tuple<GameObject , Type , string , long> ( obj , type , propertieName , index ) );
        }

        public static List<Tuple<GameObject , Type , string , long>> listForLoad=null;
    }
}
